﻿using Polly;
using Polly.Timeout;

namespace CQIE.JonJack.UtilitySource
{
    public class PollyServices
    {
        /// <summary>
        /// 回退
        /// </summary>
        public Policy<string> TestFallback()
        {
            var result = Policy<string>.Handle<Exception>() //1.定义条件
                               .Fallback(() =>              //2. 定义处理方式
                               {
                                   return "hello world";
                               });


            Console.WriteLine(result);
            return result;
        }

        /// <summary>
        /// 重试
        /// </summary>
        public Policy<string> TestRetry()
        {
            var result = Policy<string>.Handle<Exception>() //1.定义条件
                               .Retry(3);


            Console.WriteLine(result);
            return result;
        }


        /// <summary>
        /// 重试N次
        /// </summary>
        public Policy<string> TestRetry2()
        {
            var result = Policy<string>.Handle<Exception>() //1.定义条件
                               .Retry(3, (ex, retryCount) =>
                               { //2. 定义处理方式
                                   Console.WriteLine($"重新次数：{retryCount}: " + ex.Exception.Message);
                               });        //3. 执行业务逻辑代码


            Console.WriteLine(result);
            return result;
        }

        /// <summary>
        /// 重试+等待时间
        /// </summary>
        public Policy<string> TestRetry3()
        {
            var result = Policy<string>.Handle<Exception>() //1.定义条件
                               .WaitAndRetry(3, (retryCount, timespan) =>
                               { //2. 定义处理方式

                                   return TimeSpan.FromSeconds(2);

                               });        //3. 执行业务逻辑代码


            Console.WriteLine(result);
            return result;

        }


        /// <summary>
        /// 超时功能: 一个是悲观策略（Pessimistic），
        /// 一个是乐观策略（Optimistic）。
        /// 其中，悲观策略超时后会直接抛异常，而乐观策略则不会，
        /// 而只是触发CancellationTokenSource.Cancel函数，需要等待委托自行终止操作
        /// </summary>
        public AsyncTimeoutPolicy TestTimeOut()
        {
            var result = Policy.TimeoutAsync(5, TimeoutStrategy.Optimistic); //执行业务逻辑代码

            Console.WriteLine($"Timeout");
            Console.WriteLine(result);
            return result;
        }

        /// <summary>
        /// 熔断
        /// </summary>
        public Policy TestCircuitBreaker()
        {

            var circuitBreakerPolicy = Policy.Handle<Exception>()
                                             .CircuitBreaker(3, TimeSpan.FromSeconds(30),
                                                              onBreak: (Exception, TimeSpan) =>
                                                              {
                                                                  Console.WriteLine("断路器：开启状态");
                                                              },
                                                              onReset: () =>
                                                              {
                                                                  Console.WriteLine("断路器：关闭状态");
                                                              },
                                                              onHalfOpen: () =>
                                                              {
                                                                  Console.WriteLine("断路器：半开启状态");
                                                              });
            return circuitBreakerPolicy;

        }
        /// <summary>
        /// 组合策略
        /// </summary>
        public Policy<string> TestWrapPolicy()
        {
            var retry = Policy<string>.Handle<Exception>().Retry(3);

            var fallback = Policy<string>.Handle<Exception>()
                                         .Fallback(() =>
                                         {
                                             return "hello world";
                                         });


            var result = Policy.Wrap(fallback, retry);   // 策略的优先级是右到左

            Console.WriteLine(result);
            return result;
        }

        /// <summary>
        /// 组合策略：熔断降级
        /// </summary>
        public Policy<string> TestWrapPolicy_2()
        {
            var fallbackPolicy = Policy<string>.Handle<Exception>()
                                         .Fallback(() =>
                                         {
                                             return "hello world";
                                         });

            var circuitBreakerPolicy = Policy<string>.Handle<Exception>()
                                             .CircuitBreaker(3,
                                                              TimeSpan.FromSeconds(5),
                                                              onBreak: (Exception, TimeSpan) =>
                                                              {
                                                                  Console.WriteLine("-------断路器：开启状态");
                                                              },
                                                              onReset: () =>
                                                              {
                                                                  Console.WriteLine("-------断路器：关闭状态");
                                                              },
                                                              onHalfOpen: () =>
                                                              {
                                                                  Console.WriteLine("-------断路器：半开启状态");
                                                              });

            var wrapPolicy = Policy.Wrap(fallbackPolicy, circuitBreakerPolicy);   // 策略的优先级是右到左

            return wrapPolicy;

        }
    }
}
